/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.beans; import java.awt.datatransfer.Transferable; import java.beans.*; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ResourceBundle; import org.openide.src.*; import org.openide.src.nodes.*; import org.openide.nodes.*; import org.openide.actions.*; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.WeakListener; import org.openide.util.actions.SystemAction; import org.openide.TopManager; import org.openide.NotifyDescriptor; /** Superclass of nodes representing elements in the source hierarchy. * <p>Element nodes generally: * <ul> * <li>Have an associated icon, according to {@link #resolveIconBase}. * <li>Have a display name based on the element's properties, using {@link #elementFormat}; * changes to {@link ElementFormat#dependsOnProperty relevant} element properties * automatically affect the display name. * <li>Have some node properties (displayable on the property sheet), according to * the element's properties, and with suitable editors. * <li>Permit renames and deletes, if a member element and writeable. * <li>As permitted by the element, and a writable flag in the node, * permit cut/copy/paste operations, as well as creation of new members. * </ul> * * @author Petr Hrebejk */ public abstract class PatternNode extends AbstractNode implements IconBases, PatternProperties, PropertyChangeListener { /** Source of the localized human presentable strings. */ static ResourceBundle bundle = NbBundle.getBundle(PatternNode.class); /** Options for the display name format. */ protected static final SourceOptions sourceOptions = new SourceOptions(); /** Default return value of getIconAffectingProperties method. */ private static final String[] ICON_AFFECTING_PROPERTIES = new String[] { PROP_MODE }; /** Array of the actions of the java methods, constructors and fields. */ private static final SystemAction[] DEFAULT_ACTIONS = new SystemAction[] { SystemAction.get(OpenAction.class), null, /* SystemAction.get(CutAction.class), SystemAction.get(CopyAction.class), null, */ SystemAction.get(DeleteAction.class), SystemAction.get(RenameAction.class), null, //SystemAction.get(ToolsAction.class), SystemAction.get(PropertiesAction.class), }; /** Associated pattern. */ protected Pattern pattern; /** Is this node read-only or are modifications permitted? */ protected boolean writeable; /** Listener to forbid its garbage collection */ private transient PropertyChangeListener listener; /** Create a new pattern node. * * @param element element to represent * @param children child nodes * @param writeable <code>true</code> if this node should allow modifications. * These include writable properties, clipboard operations, deletions, etc. */ public PatternNode(Pattern pattern, Children children, boolean writeable) { super(children); this.pattern = pattern; this.writeable = writeable; setIconBase(resolveIconBase()); setDefaultAction(SystemAction.get(OpenAction.class)); setActions(DEFAULT_ACTIONS); //this.pattern.addPropertyChangeListener(new WeakListener.PropertyChange (this)); this.pattern.addPropertyChangeListener( WeakListener.propertyChange (this, this.pattern)); displayFormat = null; } /* Gets the short description of this node. * @return A localized short description associated with this node. */ public String getShortDescription() { return super.getShortDescription(); // If not ovewloaded in ancestors } /** Get the currently appropriate icon base. * Subclasses should make this sensitive to the state of the element--for example, * a private variable may have a different icon than a public one. * The icon will be automatically changed whenever a * {@link #getIconAffectingProperties relevant} change is made to the element. * @return icon base * @see AbstractNode#setIconBase */ abstract protected String resolveIconBase(); /** Get the names of all element properties which might affect the choice of icon. * The default implementation just returns {@link #PROP_MODIFIERS}. * @return the property names, from {@link ElementProperties} */ protected String[] getIconAffectingProperties() { return ICON_AFFECTING_PROPERTIES; } public HelpCtx getHelpCtx () { return new HelpCtx (PatternNode.class); } /** Test whether this node can be renamed. * The default implementation assumes it can if this node is {@link #writeable}. * * @return <code>true</code> if this node can be renamed */ public boolean canRename() { return writeable; } /** Test whether this node can be deleted. * The default implementation assumes it can if this node is {@link #writeable}. * * @return <code>true</code> if this node can be renamed */ public boolean canDestroy () { return writeable; } /* Copy this node to the clipboard. * * @return {@link ExTransferable.Single} with one flavor, {@link NodeTransfer#nodeCopyFlavor} * @throws IOException if it could not copy */ public Transferable clipboardCopy () throws IOException { //PENDING return super.clipboardCopy(); } /* Cut this node to the clipboard. * * @return {@link ExTransferable.Single} with one flavor, {@link NodeTransfer#nodeCopyFlavor} * @throws IOException if it could not cut */ public Transferable clipboardCut () throws IOException { if (!writeable) throw new IOException(); //PENDING return super.clipboardCopy(); } /** Test whether this node can be copied. * The default implementation returns <code>true</code>. * @return <code>true</code> if it can */ public boolean canCopy () { return true; } /** Test whether this node can be cut. * The default implementation assumes it can if this node is {@link #writeable}. * @return <code>true</code> if it can */ public boolean canCut () { return writeable; } /** Set all actions for this node. * @param actions new list of actions */ public void setActions(SystemAction[] actions) { systemActions = actions; } /** Calls super.fireCookieChange. The reason why is redefined * is only to allow the access from this package. */ void superFireCookieChange() { fireCookieChange(); } /** Get a cookie from this node. * First tries the node itself, then {@link Element#getCookie}. * Since {@link Element} implements <code>Node.Cookie</code>, it is * possible to find the element from a node using code such as: * <p><code><pre> * Node someNode = ...; * MethodElement element = (MethodElement) someNode.getCookie (MethodElement.class); * if (element != null) { ... } * </pre></code> * @param type the cookie class * @return the cookie or <code>null</code> */ public Node.Cookie getCookie (Class type) { Node.Cookie c = super.getCookie(type); if (c == null) c = pattern.getCookie(type); return c; } /** Test for equality. * @return <code>true</code> if the represented {@link Element}s are equal */ public boolean equals (Object o) { return (o instanceof PatternNode) && (pattern.equals (((PatternNode)o).pattern)); } /** Get a hash code. * @return the hash code from the represented {@link Element} */ public int hashCode () { return pattern.hashCode (); } /** Called when node name is changed */ public void superSetName(String name) { super.setName( name ); } /** Set's the name of pattern. Must be defined in descendants */ abstract protected void setPatternName(String name) throws SourceException; /** Create a node property representing the pattern's name. * @param canW if <code>false</code>, property will be read-only * @return the property. */ protected Node.Property createNameProperty(boolean canW) { return new PatternPropertySupport(PatternProperties.PROP_NAME, String.class, canW) { /** Gets the value */ public Object getValue () { return ((Pattern)pattern).getName(); } /** Sets the value */ public void setValue(Object val) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { super.setValue(val); try { String str = (String) val; pattern.patternAnalyser.setIgnore( true ); setPatternName( str ); pattern.patternAnalyser.setIgnore( false ); } catch (SourceException e) { throw new InvocationTargetException(e); } catch (ClassCastException e) { throw new IllegalArgumentException(); } } }; } /** Called when the node has to be destroyed */ public void destroy() throws IOException { try { pattern.destroy(); } catch (SourceException e) { throw new IOException(e.getMessage()); } super.destroy(); } // ================== Pattern listener ================================= public void propertyChange(PropertyChangeEvent evt) { setIconBase( resolveIconBase() ); superSetName( pattern.getName() ); firePropertyChange( null, null, null ); } // ================== Property support for element nodes ================= /** Property support for element nodes properties. */ static abstract class PatternPropertySupport extends PropertySupport { /** Constructs a new ElementProp - support for properties of * element hierarchy nodes. * * @param name The name of the property * @param type The class type of the property * @param canW The canWrite flag of the property */ public PatternPropertySupport(String name, java.lang.Class type, boolean canW) { super(name, type, bundle.getString("PROP_" + name), bundle.getString("HINT_" + name), true, canW); } /** Setter for the value. This implementation only tests * if the setting is possible. * * @param val the value of the property * @exception IllegalAccessException when this ElementProp was constructed * like read-only. */ public void setValue (Object val) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { if (!canWrite()) throw new IllegalAccessException(bundle.getString("MSG_Cannot_Write")); } } } /* * Log * 9 Gandalf 1.8 1/15/00 Petr Hrebejk BugFix 5386, 5385, 5393 * and new WeakListener implementation * 8 Gandalf 1.7 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 7 Gandalf 1.6 9/24/99 Petr Hrebejk Rename of properties * from popupmenu fixed * 6 Gandalf 1.5 9/13/99 Petr Hrebejk Creating multiple * Properties/EventSet with the same name vorbiden. Forms made i18n * 5 Gandalf 1.4 7/28/99 Petr Hrebejk Property Mode change fix * 4 Gandalf 1.3 7/26/99 Petr Hrebejk Better implementation of * patterns resolving * 3 Gandalf 1.2 7/21/99 Petr Hrebejk Bug fixes interface * bodies, is for boolean etc * 2 Gandalf 1.1 7/8/99 Jesse Glick Context help. * 1 Gandalf 1.0 6/28/99 Petr Hrebejk * $ */